package org.eenie.core.ext


import android.app.Dialog
import androidx.lifecycle.*

import kotlinx.coroutines.*


val ViewModel.lifecycleScope: CoroutineScope
    get() {
        return viewModelScope
    }


fun LifecycleCoroutineScope.launchWithDialog(
    dialog: Dialog? = null,
    onError: (Throwable) -> Unit = {
        it.printStackTrace()
    },
    block: suspend CoroutineScope.() -> Unit,
): Job {
    val job = launch {
        dialog?.show()
        runCatching {
            block.invoke(this)
        }.onSuccess {
            dialog?.dismiss()
        }.onFailure {
            onError.invoke(it)
            dialog?.dismiss()
        }
        dialog?.dismiss()
    }
    dialog?.setOnCancelListener {
        job.cancel()
    }
    return job
}


fun CoroutineScope.launchWithDialog(
    dialog: Dialog? = null,
    onError: (Throwable) -> Unit = {
        it.printStackTrace()
    },
    block: suspend CoroutineScope.() -> Unit,
): Job {
    val job = launch {
        dialog?.show()
        runCatching {
            block.invoke(this)
        }.onSuccess {
            dialog?.dismiss()
        }.onFailure {
            onError.invoke(it)
            dialog?.dismiss()
        }
        dialog?.dismiss()
    }
    dialog?.setOnCancelListener {
        job.cancel()
    }
    return job
}


fun CoroutineScope.launchWithLoadingProvider(
    loading: ILoadingProvider? = null,
    onError: (Throwable) -> Unit = {
        it.printStackTrace()
    },
    block: suspend CoroutineScope.() -> Unit,
): Job {
    val job = launch {
        loading?.showLoading()
        runCatching {
            block.invoke(this)
        }.onSuccess {
            loading?.hideLoading()
        }.onFailure {
            onError.invoke(it)
            loading?.hideLoading()
        }
        loading?.hideLoading()
    }
    loading?.setOnCancelListener {
        job.cancel()
    }
    return job
}


fun CoroutineScope.launchWithCondition(
    condition: () -> Boolean,
    block: suspend CoroutineScope.() -> Unit,
    duration: Long = 5000,
    frequency: Long = 500
): Job = this.launch {

    var flag = !condition.invoke()
    withTimeout(duration) {
        while (flag) {
            delay(frequency)
            flag = !condition.invoke()
        }
        block.invoke(this)
    }

}

